{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Clojure\n",
    "\n",
    "[Clojure](http://clojure.org/) is a dialect of Lisp that runs in the JVM.\n",
    "It shares with Lisp the code-as-data philosophy and a powerful macro system.\n",
    "Clojure is predominantly a functional programming language, and features a rich set of immutable, persistent data structures.\n",
    "It has strong support for reliable multithreading and concurrency."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "; lazy infinite sequence with recursive definition\n",
    "(def fib-seq-lazy \n",
    "  ((fn rfib [a b] \n",
    "     (lazy-seq (cons a (rfib b (+ a b)))))\n",
    "   0 1))\n",
    "(take 20 fib-seq-lazy)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "; 'unless' cannot be defined with a function because\n",
    "; it does not always evaluate both its arguments.\n",
    "(defmacro unless [pred a b]\n",
    "  `(if (not ~pred) ~a ~b))\n",
    "(unless false (println \"Will print\") (println \"Will not print\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(defn run [nvecs nitems nthreads niters]\n",
    "  (let [vec-refs (vec (map (comp ref vec)\n",
    "                           (partition nitems (range (* nvecs nitems)))))\n",
    "        swap #(let [v1 (rand-int nvecs)\n",
    "                    v2 (rand-int nvecs)\n",
    "                    i1 (rand-int nitems)\n",
    "                    i2 (rand-int nitems)]\n",
    "                (dosync\n",
    "                 (let [temp (nth @(vec-refs v1) i1)]\n",
    "                   (alter (vec-refs v1) assoc i1 (nth @(vec-refs v2) i2))\n",
    "                   (alter (vec-refs v2) assoc i2 temp))))\n",
    "        report #(do\n",
    "                 (prn (map deref vec-refs))\n",
    "                 (println \"Distinct:\"\n",
    "                          (count (distinct (apply concat (map deref vec-refs))))))]\n",
    "    (report)\n",
    "    (dorun (apply pcalls (repeat nthreads #(dotimes [_ niters] (swap)))))\n",
    "    (report)))\n",
    "; When run, we see no values get lost or duplicated in the shuffle.\n",
    "; There are 36 distinct numbers before and after. \n",
    "(run 6 6 6 100000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Using the classpath to load a jar\n",
    "\n",
    "This first cell shows that you get an error if you try to import a class not built-in to BeakerX:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(import com.beaker.BeakerXClasspathTest)\n",
    "(def classpathTest (new BeakerXClasspathTest))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The magic `%classpath` allows you to add jars to your kernel."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%classpath add jar ../resources/jar/BeakerXClasspathTest.jar"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(import com.beaker.BeakerXClasspathTest)\n",
    "(def classpathTest (new BeakerXClasspathTest))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(BeakerXClasspathTest/staticTest)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(. classpathTest getObjectTest)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Array of Maps with Properties"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "[{:foo 1}{:foo 2}]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Interactive Plot"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(import '[com.twosigma.beakerx.chart.xychart Plot]\n",
    "        '[com.twosigma.beakerx.chart.xychart.plotitem Line])\n",
    "(doto (Plot.)\n",
    "            (.setTitle \"We Will Control the Title\")\n",
    "            (.setXLabel \"Horizontal\")\n",
    "            (.setYLabel \"Vertical\")\n",
    "            (.add (doto (Line.)\n",
    "                        (.setX [0, 1, 2, 3, 4, 5])\n",
    "                        (.setY [0, 1, 6, 5, 2, 8]))))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## EasyForm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(def form (doto (com.twosigma.beakerx.easyform.EasyForm. \"Test Form\")\n",
    "                (.addTextField \"Name\")\n",
    "                (.addButton \"Reverse\" \"reverse\")))\n",
    "form"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": [
     "reverse"
    ]
   },
   "outputs": [],
   "source": [
    "(reverse (get form \"Name\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## Import/Unimport magic command"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%import com.twosigma.beakerx.widget.IntSlider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(new IntSlider)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%unimport com.twosigma.beakerx.widget.IntSlider"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(new IntSlider)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## IPyVolume visualization widget\n",
    "\n",
    "[ipyvolume](https://github.com/maartenbreddels/ipyvolume) works with Clojure, and the other [3D widgets](../groovy/3D.ipynb) probably work too.  Note, the widget JS needs to be installed in advance of starting the notebook:\n",
    "```\n",
    "conda install -c conda-forge ipyvolume\n",
    "```\n",
    "See the [source of this example](https://github.com/maartenbreddels/ipyvolume/pull/140#issuecomment-394777662)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%classpath add mvn com.github.twosigma ipyvolume master-SNAPSHOT"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(import ipyvolume.PyLab)\n",
    "\n",
    "(defn ball \n",
    "    [size radius]\n",
    "    (let [data           (make-array Float/TYPE size size size)\n",
    "          square         #(* % %)\n",
    "          center         #(- % (/ size 2))\n",
    "          sum            (partial reduce +)\n",
    "          sum-of-squares #(sum (map square %))]\n",
    "        (doseq [i (range size)\n",
    "                j (range size)\n",
    "                k (range size)\n",
    "                :let [[x y z] (map center [i j k])] \n",
    "                :when (> (square radius) \n",
    "                         (sum-of-squares [x y z]))]\n",
    "             (aset data i j k (float 1)))\n",
    "        data))\n",
    "(PyLab/volShow (ball 32 12))"
   ]
  }
 ],
 "metadata": {
  "beakerx_kernel_parameters": {},
  "kernelspec": {
   "display_name": "Clojure",
   "language": "clojure",
   "name": "clojure"
  },
  "language_info": {
   "codemirror_mode": "Clojure",
   "file_extension": ".clj",
   "mimetype": "text/x-clojure",
   "name": "Clojure",
   "nbconverter_exporter": "",
   "version": "1.9.0"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": false,
   "sideBar": false,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": false,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
